Para la estimación del modelo vamos a usar el 90% de los datos, es decir, el conjunto de entrenamiento va desde enero del 2001, hasta diciembre del 2018. El conjunto de prueba va desde enero del 2019 hasta marzo del 2020.
ts_desempleo<-ts(rev(datos$`Tasa de desempleo (%)`), start = c(2001,01), frequency = 12, end = c(2020,03))
xts_desempleo = as.xts(ts_desempleo)
plot(xts_desempleo, main = "Tasa de desempleo",xlab="Tiempo")
En la gráfica de la Serie de tasa de desempleo, podemos ver ya algunos componentes notorios tales como tendencia y estacionalidad. Se puede ver un posible periodo de \(S=12\) meses para la estacionalidad en donde los picos más altos parecen presentarse en los meses de principio de año y un notorio decaimiento para finales de año. En la tendencia podríamos pensar que estamos tratando con una tendencia de tipo estocástica, sin embargo, se realizaran las pruebas pertinentes para probar estadísticamente si se trata de ese tipo de tendencia. En cuanto a la varianza marginal, aunque parece constante a lo largo del tiempo, también se realizará un estudio correspondiente.
Para comenzar el análisis de la serie, vamos a seguir la metodología usada en clase, en donde se comenzará por realizar un análisis de la varianza marginal, esto lo haremos por medio del cálculo del \(\lambda\) de las transformaciones Box-Cox.
Al hacer el cálculo del \(\lambda\) por medio del método de guerrero encontramos que el valor obtenido es \(\lambda=0.5996448\), esto quiere decir que la trasnformación necesaria para la serie es \(y_t = \frac{x_t^{\lambda}-1}{\lambda}\).
lambda=forecast::BoxCox.lambda(ts_desempleo, method = "guerrero", lower = -1, upper = 3)
lambda
## [1] 0.5996448
trans_ts_desempleo=((ts_desempleo^lambda)-1)/lambda
forecast::BoxCox.lambda(trans_ts_desempleo, method = "guerrero", lower = -1, upper = 3)
## [1] 0.9906822
Al transformar la serie y volver a calcular el lambda de la trasnformación Box-Cox obtenemos un valor de \(\lambda=0.9906822\), un valor muy cercano a 1, lo que significa que la varianza se ha estabilizado de manera correcta. Cabe aclarar que entre los valores de lambda no hay mucha diferencia, por lo que se podría pensar que la trasnformación no es tan necesaria, de igual manera en el gráfico que se presenta a continuación, vemos la serie transformada, y podemos notar que no existe mucha diferencia con la gráfica original, a parte de la escala.
plot(trans_ts_desempleo, ylab = "Serie transformada")
Hemos decidido dejar la trasnformación para seguir la metodología, esperando también que en los modelos que vamos a usar la varianza no cause problemas en la estabilidad del modelo.
Para remover la tendencia, estudiamos si la serie presenta raíces unitarias. Esto con el fin de determinar si la tendencia se presenta de manera estocástica o determinística. Para ello hacemos uso de los diferentes test de raíces unitarias cuyo resultado presentamos a continuación:
12*(length(trans_ts_desempleo/100))^(0.25)
## [1] 46.0039
k=trunc((length(trans_ts_desempleo)-1)^(1/3))
ndiffs(trans_ts_desempleo)
## [1] 1
urca::ur.df(trans_ts_desempleo)
##
## ###############################################################
## # Augmented Dickey-Fuller Test Unit Root / Cointegration Test #
## ###############################################################
##
## The value of the test statistic is: -1.0598
tseries::adf.test(trans_ts_desempleo,k=k)
##
## Augmented Dickey-Fuller Test
##
## data: trans_ts_desempleo
## Dickey-Fuller = -3.0888, Lag order = 5, p-value = 0.1193
## alternative hypothesis: stationary
fUnitRoots::adfTest(trans_ts_desempleo,lag=k)
##
## Title:
## Augmented Dickey-Fuller Test
##
## Test Results:
## PARAMETER:
## Lag Order: 5
## STATISTIC:
## Dickey-Fuller: -1.4848
## P VALUE:
## 0.1423
##
## Description:
## Tue Mar 14 22:16:46 2023 by user:
dts_desempleo<-diff(trans_ts_desempleo)
d_xts_desempleo = as.xts(dts_desempleo)
Al hacer uso de la función ndiffs, obtenemos que la serie presenta una raíz unitaria. En los test se realiza el Test de Dickey-Fuller aumentado y en ambos obtenemos un p-valor mayor que un nivel de significancia del \(\alpha=0.05\%\). Por lo que aceptamos la hipótesis nula de que existe una raíz unitaria.
Por tanto asumimos que existe raíz unitaria y la tendencia de la serie es estocástica. Así el método usado para remover la tendencia es diferenciar la serie, es decir \(w_t = y_t-y_{t-1}\) donde \(w_t\) es la serie resultante.
Podemos ver el gráfico de la serie diferenciada a continuación:
plot(d_xts_desempleo, main = "Tasa desempleo diferenciada",xlab="Tiempo")
Podemos ver como la serie tiene un aparente comportamiento que fluctúa alrededor de 0, con lo que podríamos pensar que la serie se ha convertido estacionaria, salvo por la componente estacional.
A continuación presentaremos 4 modelos, basados en diferentes metodologías para abordar la estacionalidad. Se realizarán primero dos modelos asumiendo estacionalidad determinística y se modelará por medio de coeficientes de Fourier y variables Dummy, luego presentaremos dos modelos SARIMA en donde se asumirá estacionalidad estocástica. Al final del trabajo presentaremos los resultados y comparaciones entre ellos, así como su ECM, esto con el fin de seleccionar el mejor modelo posible.
Para empezar, vamos a estudiar la estacionalidad por medio de estadística descriptiva. Por lo que acudimos a los gráficos ACF y PACF.
acf(dts_desempleo, ci.type="ma", lag.max = 50)
pacf(dts_desempleo, lag.max = 50)
Vemos claramente que en el valor de 1,2,3,.. y valores cercanos a estos tenemos rezagos significativos, lo que nos indica que para la frecuencia de la serie que es 12, esta podría ser el posible período de los ciclos.
Analizamos de manera más profunda por medio de un gráfico de subseries
tbl_ts_desempleo<- as_tsibble(dts_desempleo)
tbl_ts_desempleo%>%select(value)%>%gg_season(period = "year")
## Plot variable not specified, automatically selected `y = value`
tbl_ts_desempleo%>%select(value)%>%gg_subseries(period = "year")
## Plot variable not specified, automatically selected `y = value`
En el primer gráfico vemos como la tasa de desempleo toma sus valores más altos a inicio de cada año, para después aparentemente fluctuar en 0 (En términos de la serie diferenciada) y posteriormente incrementarse al final de cada año. En el segundo, vemos diferencias significativas entre las medias de los meses, siendo más evidente esto en los meses de enero y marzo por ejemplo. Esto demuestra que existe estacionalidad con período igual a 12 meses como habíamos pensado anteriormente,
tbl_desempleo<-as_tibble(tbl_ts_desempleo)
tbl_desempleo$index<-as.Date(tbl_desempleo$index)
tbl_desempleo
Continuamos con un gráfico box-plot mensual:
tbl_desempleo%>%plot_seasonal_diagnostics(.date_var = index,.value = value,.feature_set = c("month.lbl"),.geom="boxplot")
Vemos algo muy parecido a lo que habíamos visto anteriormente, lo que fortalece nuestra hipótesis de período anual.
Finalizando, realizamos un períodograma:
spectrum(tbl_desempleo$value,log='no')
abline(v=1/12, lty=2,col="red")
abline(v=2/12, lty=2,col="blue")
abline(v=3/12, lty=2,col=4)
abline(v=4/12, lty=2,col=7)
Vemos como se producen picos de manera períodica, con la línea roja en el valor \(1/12\) que es la frecuencia de la serie, y el valor azul en \(1/6\), esto es multiplos racionales de la frecuencia.
Ahora asumiremos que la estacionalidad se presenta de manera estocástica. Continuamos con la metodología, es decir, continuaremos con la serie diferenciada y de ahí partirá nuestro análisis.
nsdiffs(dts_desempleo)
## [1] 1
Al realizar el cálculo con la función nsdiffs vemos que es necesario realizar una diferencia estacional.
Realizamos la diferencia estacional para el periodo \(s=12\) y estudiamos el ACF y PACF:
dts_st_desempleo=diff(dts_desempleo,lag=12,differences = 1)
acf(dts_st_desempleo, ci.type="ma", lag.max = 100)
pacf(dts_st_desempleo, lag.max = 100)
Como podemos ver en el ACF el rezago en \(h=s\) resulta significativo y para múltiplos de s se va para 0. En el PACF vemos que los rezagos en \(h=s,h=2s,h=3s\) resultan significativos, así como los rezagos cerca de estos, por tanto \(P=3\),\(Q=1\) son los parámetros candidatos.
Si analizamos los tres primeros rezagos en el PACF, estos resultan significativos, y en el ACF solo el primero lo es, por tanto \(p=3,q=1\) son los parámetros restantes del modelo.
Verificamos si la serie necesita una segunda diferencia estacional.
nsdiffs(dts_st_desempleo)
## [1] 0
Antes de seguir con el modelamiento se debe realizar una revisión a los posibles outliers, para ello se hará un análisis de intervenciones junto con su respectiva variable regresora que medirá y mitigará el impacto de nivel \(w_0\) de estos outliers.
library(tsoutliers)
##
## Attaching package: 'tsoutliers'
## The following object is masked from 'package:fabletools':
##
## outliers
tso(ts_desempleo)
## Series: ts_desempleo
## Regression with ARIMA(2,0,2)(2,1,0)[12] errors
##
## Coefficients:
## ar1 ar2 ma1 ma2 sar1 sar2 LS25 TC68
## 1.7649 -0.7775 -1.6484 0.7849 -0.5589 -0.2430 -2.3389 1.7769
## s.e. 0.1615 0.1570 0.1133 0.0587 0.0782 0.0773 0.3353 0.4559
##
## sigma^2 = 0.3219: log likelihood = -172.76
## AIC=363.52 AICc=364.45 BIC=393.38
##
## Outliers:
## type ind time coefhat tstat
## 1 LS 25 2003:01 -2.339 -6.975
## 2 TC 68 2006:08 1.777 3.898
product.outlier<-tso(ts_desempleo,types=c("AO","LS","TC"))
La salida nos muestra que tenemos 2 outliers en las observaciones 25 y 68. Estos son de tipo cambio de nivel y transitorio, respectivamente. Se ajusta una variable regresora para incluirla en el modelo posterior.
plot(product.outlier)
z=length(ts_desempleo)
xregresora=rep(0,z)
xregresora[c(25,68)]=1
Para el modelamiento, empezamos con la siguiente propuesta \(SARIMA(3,1,1)_{12}(3,1,1)\).
##
## z test of coefficients:
##
## Estimate Std. Error z value Pr(>|z|)
## ar1 -0.468374 0.228603 -2.0488 0.0404768 *
## ar2 -0.156311 0.180728 -0.8649 0.3870972
## ar3 -0.147504 0.093264 -1.5816 0.1137463
## ma1 -0.302644 0.224250 -1.3496 0.1771502
## sar1 -1.382912 0.178797 -7.7345 1.038e-14 ***
## sar2 -0.831543 0.148162 -5.6124 1.996e-08 ***
## sar3 -0.348256 0.073135 -4.7618 1.918e-06 ***
## sma1 0.651098 0.185552 3.5090 0.0004498 ***
## xreg 0.232641 0.136512 1.7042 0.0883480 .
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
Se ve que los componentes autoregresivos de órdenes 2 y 3 no son significativos, al igual que el componente de promedios móviles, los outliers resultan significativos al \(\alpha = 10\)%.
Por tanto si borramos estas variables, obtenemos el siguiente modelo \(SARIMA(1,1,0)_{12}(3,1,1)\).
modeloalter= Arima(ts_desempleo, c(1, 1,0),seasonal = list(order = c(3, 1, 1), period = 12),lambda = lambda)
coeftest(modeloalter)
##
## z test of coefficients:
##
## Estimate Std. Error z value Pr(>|z|)
## ar1 -0.555922 0.059071 -9.4110 < 2.2e-16 ***
## sar1 -1.299230 0.178219 -7.2901 3.097e-13 ***
## sar2 -0.784514 0.142705 -5.4974 3.853e-08 ***
## sar3 -0.359381 0.074109 -4.8494 1.239e-06 ***
## sma1 0.595199 0.185879 3.2021 0.001364 **
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
En donde sus coeficientes resultan todos significativos, pero al realizar el análisis de residuales obtuvimos una correlación no explicada en los primeros rezagos, esto puede deberse al componente de promedios móviles, por tanto, se decide añadir la componente de promedio móvil.
residuales <- modeloalter$residuals
plot(residuales)
acf(residuales,lag.max = 24)
pacf(residuales,lag.max = 24)
Box.test(residuales, lag = (length(residuales)/4), type = "Ljung-Box", fitdf = 2)
##
## Box-Ljung test
##
## data: residuales
## X-squared = 144.75, df = 52, p-value = 1.111e-10
######Análisis de Outliers
#Test de normalidad
jarque.bera.test(residuales)
##
## Jarque Bera Test
##
## data: residuales
## X-squared = 1.8008, df = 2, p-value = 0.4064
Así, obtenemos el modelo final \(SARIMA(1,1,1)_{12}(3,1,1)\) en donde todas las componentes resultan significativas también, además se decide dejar los coeficientes de regresión para los outliers.
modeloalter= Arima(ts_desempleo, c(1, 1,1),seasonal = list(order = c(3, 1, 1), period = 12),lambda = lambda, xreg = xregresora,fixed=c(NA,NA,NA,NA,NA,NA,NA))
coeftest(modeloalter)
## Warning in sqrt(diag(se)): NaNs produced
##
## z test of coefficients:
##
## Estimate Std. Error z value Pr(>|z|)
## ar1 -0.2863653 0.0971221 -2.9485 0.003193 **
## ma1 -0.4938483 0.0842829 -5.8594 4.645e-09 ***
## sar1 -1.3911324 NaN NaN NaN
## sar2 -0.8448370 0.0797717 -10.5907 < 2.2e-16 ***
## sar3 -0.3525806 0.0742133 -4.7509 2.025e-06 ***
## sma1 0.6563591 0.0057748 113.6588 < 2.2e-16 ***
## xreg 0.2240794 0.1341994 1.6697 0.094969 .
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
En el análisis de residuales vemos que aunque los residuales no tienen un comportamiento normal, no nos quedan rezagos por explicar. Es decir, nuestro modelo logra explicar la estructura de autocorrelación de la serie. Adicionalmente en la prueba de Ljung-Box obtuvimos que no nos queda autocorrelación por explicar.
residuales <- modeloalter$residuals
plot(residuales)
acf(residuales,lag.max = 20)
pacf(residuales,lag.max = 20)
Box.test(residuales, lag = (length(residuales)/4), type = "Ljung-Box", fitdf = 2)
##
## Box-Ljung test
##
## data: residuales
## X-squared = 91.92, df = 52, p-value = 0.000536
######Análisis de Outliers
#Test de normalidad
jarque.bera.test(residuales)
##
## Jarque Bera Test
##
## data: residuales
## X-squared = 9.8352, df = 2, p-value = 0.007317
Las estadísticas CUSUM y CUSUMQS se visualizan estables. Lo cual significa que nuestros parámetros son estables en el tiempo.
###Estad?ticas CUSUM
res=residuales
cum=cumsum(res)/sd(res)
N=length(res)
cumq=cumsum(res^2)/sum(res^2)
Af=0.948 ###Cuantil del 95% para la estad?stica cusum
co=0.14803####Valor del cuantil aproximado para cusumsq para n/2
LS=Af*sqrt(N)+2*Af*c(1:length(res))/sqrt(N)
LI=-LS
LQS=co+(1:length(res))/N
LQI=-co+(1:length(res))/N
plot(cum,type="l",ylim=c(min(LI),max(LS)),xlab="t",ylab="",main="CUSUM")
lines(LS,type="S",col="red")
lines(LI,type="S",col="red")
#CUSUM Square
plot(cumq,type="l",xlab="t",ylab="",main="CUSUMSQ")
lines(LQS,type="S",col="red")
lines(LQI,type="S",col="red")
Para la ventana de Rolling Usamos el conjunto completo de datos para reajustar el modelo, por tanto, volvemos a leer los datos.
ts_desempleo<-ts(rev(datos$`Tasa de desempleo (%)`), start = c(2001,01), frequency = 12, end = c(2020,03))
z=length(ts_desempleo)
xregresora=rep(0,z)
xregresora[c(25,68)]=1
xregresora
## [1] 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0
## [38] 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0
## [75] 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
## [112] 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
## [149] 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
## [186] 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
## [223] 0 0 0 0 0 0 0 0 0
Como se había mencionado anteriormente el conjunto de entrenamiento va desde enero del 2001 hasta diciembre del 2018, y el conjunto de prueba va desde enero del 2019 hasta marzo del 2020.
#####Comparación de pronósticos####
library(fpp)
## Loading required package: fma
## Loading required package: expsmooth
##
## Attaching package: 'fpp'
## The following object is masked from 'package:fpp3':
##
## insurance
train <- window(ts_desempleo,start=c(2001,01),end=c(2018,12))
test <- window(ts_desempleo,start=c(2019,01),end=c(2020,03))
fitmodelo <- Arima(ts_desempleo, c(1, 1,1),seasonal = list(order = c(3, 1, 1), period = 12),lambda = lambda, xreg = xregresora,fixed=c(NA,NA,NA,NA,NA,NA,NA))
refit <- Arima(ts_desempleo, model=fitmodelo,xreg = xregresora)
fc <- window(fitted(refit), start=c(2019,01))
h <- 1
train <- window(ts_desempleo,start=c(2001,01),end=c(2018,12))
test <- window(ts_desempleo,start=c(2019,01),end=c(2020,03))
n <- length(test) - h + 1
fitmodelo <- Arima(ts_desempleo, c(1, 1,1),seasonal = list(order = c(3, 1, 1), period = 12),lambda = lambda, xreg = xregresora,fixed=c(NA,NA,NA,NA,NA,NA,NA))
fc <- ts(numeric(n), start=c(2019,01), freq=12)
for(i in 1:n)
{
x <- window(ts_desempleo, end=c(2018, 12+(i-1)))
z=length(x)
xregresora=rep(0,z)
xregresora[c(25,68)]=1
refit <- Arima(x, model=fitmodelo,xreg = xregresora)
fc[i] <- forecast::forecast(refit,xreg = xregresora, h=h)$mean[h]
}
dife=(test-fc)^2
ecm=(1/(length(test)))*sum(dife)
ecm
## [1] 0.264623
Así obtenemos un ECM un paso adelante de 0.261742, lo cuál significa que nuestro modelo es bastante funcional.
z=length(ts_desempleo)
xregresora=rep(0,z)
xregresora[c(25,68)]=1
modelo_final<-Arima(ts_desempleo, c(1, 1,0),seasonal = list(order = c(3, 1, 1), period = 12),lambda = lambda)
predicciones<-forecast::forecast(modelo_final,xreg = xregresora, h=24)
## Warning in forecast.forecast_ARIMA(modelo_final, xreg = xregresora, h = 24):
## xreg not required by this model, ignoring the provided regressors
plot(predicciones, main = "Pronóstico a dos años")
Podemos ver como el modelo se ajusta a nuestros datos de excelente manera y aunque no se cumplen estrictamente los supuestos del modelo, esto no presenta un problema mayor para la estimación.